import React, { useEffect, useState } from 'react'
import styles from './index.module.less'
import G6 from '@antv/g6'
import OPEN from './register/img/open.png'
import CLOSE from './register/img/close.png'

G6.registerNode(
	'model-node',
	{
		drawShape(cfg, group) {
			const { openIcon, hideIcon } = cfg

			// 添加节点
			const shape = group.addShape('rect', {
				name: 'model-node',
				draggable: true, // 让自定义节点支持拖拽
				attrs: cfg.style,
			})

			const openSwitch = group.addShape('circle', {
				draggable: true,
				attrs: {
					r: 10,
					...openIcon,
					...openIcon.style,
				},
				className: 'state-open',
			})

			const hideSwitch = group.addShape('circle', {
				draggable: true,
				attrs: {
					r: 10,
					...hideIcon,
					...hideIcon.style,
				},
				className: 'state-hide',
			})

			// 添加多行文本
			for (let i = 0; i < cfg.labels.length; i++) {
				const item = cfg.labels[i]
				const {
					label,
					labelCfg: { maxlength },
					className,
				} = item

				let text = maxlength ? label.substr(0, maxlength) : label || ''

				if (label.length > maxlength) {
					text = `${text}...`
				}

				group.addShape('text', {
					attrs: {
						text,
						...item,
						...item.labelCfg,
					},
				})
			}

			this.bindEvent(group, openSwitch)
			this.bindEvent(group, hideSwitch)

			return shape
		},
		bindEvent(group, btn) {
			btn.on('click', () => {
				const open = group.get('children').find((child) => child.cfg.className === 'state-open')
				const close = group.get('children').find((child) => child.cfg.className === 'state-hide')

				if (btn.cfg.className === 'state-open') {
					const item = group.get('item')
					const model = item.getModel()

					open.toBack()
					close.toFront()
					model.style.height = 100
					item.update(model)
				} else if (btn.cfg.className === 'state-hide') {
					const item = group.get('item')
					const model = item.getModel()

					close.toBack()
					open.toFront()
					model.style.height = 50
					item.update(model)
				}
			})
		},
	},
	'single-node'
) // 继承自内置节点

G6.registerEdge('line-arrow', {
	options: {
		style: {
			stroke: '#ccc',
		},
	},
	draw: function draw(cfg, group) {
		const startPoint = cfg.startPoint
		const endPoint = cfg.endPoint

		const stroke = (cfg.style && cfg.style.stroke) || this.options.style.stroke
		const startArrow = (cfg.style && cfg.style.startArrow) || undefined
		const endArrow = (cfg.style && cfg.style.endArrow) || undefined
		const a = (endPoint.y - startPoint.y) / 4
		const keyShape = group.addShape('path', {
			attrs: {
				path: [
					['M', startPoint.x, startPoint.y],
					['L', startPoint.x, startPoint.y + a],
					['L', startPoint.x / 3 + endPoint.x, startPoint.y + a],
					['L', startPoint.x / 3 + endPoint.x, endPoint.y - a],
					['L', startPoint.x, endPoint.y - a],
					['L', endPoint.x, endPoint.y],
				],
				stroke,
				lineWidth: 1,
				startArrow,
				endArrow,
			},
			className: 'edge-shape',
			name: 'edge-shape',
		})
		return keyShape
	},
})

const fittingString = (str, maxWidth, fontSize) => {
	const ellipsis = '...'
	const ellipsisLength = G6.Util.getTextSize(ellipsis, fontSize)[0]
	let currentWidth = 0
	let res = str
	const pattern = new RegExp('[\u4E00-\u9FA5]+') // distinguish the Chinese charactors and letters
	str.split('').forEach((letter, i) => {
		if (currentWidth > maxWidth - ellipsisLength) return
		if (pattern.test(letter)) {
			// Chinese charactors
			currentWidth += fontSize
		} else {
			// get the width of single letter according to the fontSize
			currentWidth += G6.Util.getLetterWidth(letter, fontSize)
		}
		if (currentWidth > maxWidth - ellipsisLength) {
			res = `${str.substr(0, i)}${ellipsis}`
		}
	})
	return res
}

const globalFontSize = 12

const Test = () => {
	// 根据官网例子的接口获取的数据
	const data = {
		nodes: [
			{
				id: 'Model',
				type: 'model-node',
				x: 100,
				y: 100,
				style: {
					width: 160,
					height: 100,
					fill: '#f1b953',
					stroke: '#f1b953',
				},
				openIcon: {
					x: 180, // 控制图标在横轴上的位置
					y: 45, // 控制图标在纵轴上的位置
					fontSize: 20,
					style: {
						fill: '#fc0',
					},
				},
				hideIcon: {
					x: 180, // 控制图标在横轴上的位置
					y: 45, // 控制图标在纵轴上的位置
					fontSize: 20,
					style: {
						fill: '#666',
					},
				},
				labels: [
					{
						x: 10,
						y: 20,
						label: '标题,最长10个字符~~',
						labelCfg: {
							fill: '#666',
							fontSize: 14,
							maxlength: 10,
						},
					},
					{
						x: 10,
						y: 40,
						label: '描述,最长12个字符~~~',
						labelCfg: {
							fontSize: 12,
							fill: '#999',
							maxlength: 12,
						},
					},
				],
			},
			{
				id: '7',
				x: 150,
				y: 100,
				size: 40,
				anchorPoints: [
					[1, 0.5],
					[1, 0],
				],
			},
			{
				id: '8',
				x: 300,
				y: 200,
				size: 40,
				anchorPoints: [
					[0, 0.5],
					[0, 1],
				],
			},
		],
		edges: [
			{
				source: '7',
				target: '8',
				sourceAnchor: 0,
				targetAnchor: 0,
			},
		],
	}

	// data.nodes.forEach(function (node) {
	//     if (node.type === "customNode") {
	//         node.firstText = fittingString(node.firstText, node.width, globalFontSize);
	//         node.secondText = fittingString(node.secondText, node.width, globalFontSize);
	//         node.thirdText = fittingString(node.thirdText, node.width, globalFontSize);
	//     }
	// });

	const [graph, setGraph] = useState(null) // 设置画布

	// 初始化画布
	const setGraphObj = () => {
		const graph = new G6.Graph({
			container: 'container',
			width: 1500,
			height: 800,
			modes: {
				default: ['drag-canvas', 'drag-node'],
			},
			defaultNode: {
				style: {
					fill: '#DEE9FF',
					stroke: '#5B8FF9',
				},
				linkPoints: {
					left: true,
					right: true,
					fill: '#fff',
					stroke: '#1890FF',
					size: 3,
				},
			},
			defaultEdge: {
				type: 'line-arrow',
				style: {
					stroke: '#F6BD16',
					startArrow: {
						path: 'M 0,0 L 12,6 L 9,0 L 12,-6 Z',
						fill: '#F6BD16',
					},
					endArrow: {
						path: 'M 0,0 L 12,6 L 9,0 L 12,-6 Z',
						fill: '#F6BD16',
					},
				},
			},
			nodeStateStyles: {
				unselected: {
					openIcon: {
						img: OPEN,
					},
					text1: {
						stroke: 'blue',
					},
					text2: {
						stroke: 'blue',
					},
					text3: {
						stroke: 'transparent',
					},
					rect: {
						stroke: 'blue',
						height: 40,
					},
				},
				selected: {
					rect: {
						stroke: 'red',
						height: 80,
					},
					openIcon: {
						img: CLOSE,
					},
					text1: {
						stroke: 'red',
					},
					text2: {
						stroke: 'green',
					},
					text3: {
						stroke: 'gray',
					},
				},
			},
		})

		setGraph(graph)
	}

	useEffect(() => {
		setGraphObj() // 初始化画布
	}, [])

	useEffect(() => {
		if (graph && data) {
			renderGraph() // 渲染画布
		}
	}, [data, graph])

	const renderGraph = () => {
		graph.clear() // 清除画布
		graph.data(data) // 传递数据
		graph.render() // 渲染画布
	}

	return <div className={styles.testBox} id={'container'} />
}

export default Test
